We suggest observing the following guidelines to produce code without the more common portability problems. They can be followed from the beginning in developing new code, or adopted incrementally as portability problems are identified.
In a header file which can be included in each of the program's source files, define (typedef) a type for each of the following functions:
typedef signed char int8_t
typedef unsigned char uint8_t
...
typedef unsigned long long uint64_t
typedef signed long intscaled_t
typedef unsigned long uintscaled_t
Be careful that constants are specified with appropriate type specifiers so that they extend to the size required by the context with the values that you require. Bit masks can be particularly troublesome in this regard:avoid using constants for negative values. For example, 0xffffffff may be equivalent to a -1 on 32-bit systems, but it is interpreted as 4,294,967,295 (signed or unsigned) on 64-bit systems. The inttypes.h header file provides cpp macros to facilitate this conversion.
Defining constants which are sensitive to type sizes in a central header file may help in modifying them when a new port is done. Where printf()/scanf() are used for objects whose types are typedef'ed differently among the targets you must support, you may need to define constant format strings for each of the types defined in step (1), for example:
#define _fmt32 "%d" #define _fmt32u "%u" #define _fmt64 "%ld" #define _fmt64u "%lu"The inttypes.h header file also defines printf()/scanf() format extensions to standardize these practices.